package be.scond.cartpool.API;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import be.scond.cartpool.exceptions.GroupDoesNotExistException;
import be.scond.cartpool.exceptions.GroupExistsException;
import be.scond.cartpool.exceptions.GroupPassIncorrectException;
import be.scond.cartpool.exceptions.UserExistsException;
import be.scond.cartpool.exceptions.UserNotFoundException;
import be.scond.cartpool.exceptions.WrongPasswordException;
import be.scond.cartpool.model.Group;
import be.scond.cartpool.model.User;
import be.scond.utils.PMF;
import be.scond.utils.ReadablePassword;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

public class GroupApi {

	public static Group register(String userName, String email, String password, String groupName, String groupPass) throws GroupPassIncorrectException, GroupDoesNotExistException, GroupExistsException, UserExistsException {
		email = email.toLowerCase();
		groupName = groupName.toLowerCase();
		
		if(groupPass.equals("")){
			try {
				Group g = registerGroup(groupName, userName, email, password);
				return g;
			} catch (GroupExistsException e) {
				throw e;
			}
		}else{
			try {
				User u = registerUserWithGroup(userName, email, groupName, groupPass, password);
				return u.getGroup();
			} catch (UserExistsException e) {
				throw e;
			} catch (GroupDoesNotExistException e) {
				throw e;
			} catch (GroupPassIncorrectException e) {
				throw e;
			} catch (UnsupportedOperationException e){
				throw new GroupPassIncorrectException();
			}
		}
	}
	
	public static Group registerGroup(String groupName, String userName, String email, String password) throws GroupExistsException {
		PersistenceManager pm = PMF.get().getPersistenceManager();
				
		try{
			Key k = KeyFactory.createKey(Group.class.getSimpleName(), groupName);
			Group g = pm.getObjectById(Group.class, k); // to throw the not found exception
			String n = g.getName();
			pm.close();
			throw new GroupExistsException("the group you tried to create with name "+n+" already exists ");
        } catch (JDOObjectNotFoundException notFoundExpection){
			
			// group does not exist
			Group newGroup = new Group();
			Key key = KeyFactory.createKey(Group.class.getSimpleName(), groupName);
			newGroup.setKey(key);
			newGroup.setName(groupName);
			String newPassword = ReadablePassword.generate(5);
			newGroup.setPassword(newPassword);
			
			User newUser = new User();
			Key userKey = new KeyFactory.Builder(Group.class.getSimpleName(), groupName).addChild(User.class.getSimpleName(), email).getKey();
			newUser.setKey(userKey);
			newUser.setName(userName);
			newUser.setEmail(email);
			newUser.setPassword(password);
			newUser.setSaldo(BigDecimal.ZERO);
			
			// a newGroup needs an new List
			List<User> userList = new ArrayList<User>();
			userList.add(newUser);
			newGroup.setUsers(userList);
			
			try{
				pm.makePersistent(newGroup);
			}finally{
				pm.close();
			}
			
			Properties props = new Properties();
			Session session = Session.getDefaultInstance(props, null);
			
			String msgBody = "Hi " + userName + ",<br/>" +
			"<br/>" +
			"Welcome to cartpool!" +
			"please keep this key!<br/><br/>" +
			"<b><h2>key: "+newPassword+"</h2></b>" +
			"<br/><br/>" +
			"your fellow shoppers will need it to register to your group" +
			"<br/><br/>" +
			"have fun using ***!" +
			"<a href='http://cartpool.appspot.com/#/home/login' alt='cartpool'>take me to my cartpool</a>";
			
			try {
				Message msg = new MimeMessage(session);
				msg.setFrom(new InternetAddress("fragilem17@gmail.com"));
				msg.addRecipient(Message.RecipientType.TO, new InternetAddress(email, userName));
				msg.setSubject("You've registered '"+groupName+"' on kmutolle - please take a second to activate it.");
				msg.setContent(msgBody, "text/html");
				Transport.send(msg);
			} catch (AddressException e) {
				// ...
			} catch (MessagingException e) {
				// ...
			} catch (UnsupportedEncodingException e) {
				// ...
			}

			return newGroup;
		}
	}
	
	public static void confirmGroup(String name) throws GroupDoesNotExistException {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try{
			Group g = getGroup(pm, name);
        	g.setConfirmed(true);
        	pm.close();
        } catch (GroupDoesNotExistException e){
        	throw e;
        }
	}	
		
	public static void deleteGroup(String name) throws GroupDoesNotExistException {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try{
			Group g = getGroup(pm, name);
			pm.deletePersistent(g);
        	pm.close();
        } catch (GroupDoesNotExistException e){
        	throw e;
        }
	}
	
	public static boolean groupExists(String groupName) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try{
			getGroup(pm, groupName);
			pm.close();
			return true;
        } catch (GroupDoesNotExistException e){
        	pm.close();
        	return false;
        }
	}
	
	public static Group getGroup(PersistenceManager pm, String groupName) throws GroupDoesNotExistException {
		groupName = groupName.toLowerCase();
		try{
			Key k = KeyFactory.createKey(Group.class.getSimpleName(), groupName);
			Group g = pm.getObjectById(Group.class, k);
			return g;
		} catch (JDOObjectNotFoundException e){
			throw new GroupDoesNotExistException();
		}
	}

	@SuppressWarnings("unchecked")
	public static List<Group> getAllGroups() {
        String query = "select from " + Group.class.getName();
        PersistenceManager pm = PMF.get().getPersistenceManager();
        List<Group> groups;
        groups = (List<Group>) pm.newQuery(query).execute();
        return groups;
	}
	
	public static User registerUserWithGroup(String userName, String email, String groupName, String groupPass, String password) throws GroupPassIncorrectException, GroupDoesNotExistException, UserExistsException {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		
		try {
			UserApi.login(email, groupName, password);
			throw new UserExistsException();
		} catch (UserNotFoundException e) {
			try{
				Group g = getGroup(pm, groupName);
				
				// iterate over the users and make sure a user with the same name does not exist.
				
				if(g.getPassword().equals(groupPass)){
					List<User> users = g.getUsers();
					Boolean userNameFound = false;
					@SuppressWarnings("unused")
					int usersFound = users.size(); //get the size so the for loop wont crash		
					
					for (User user : users) {
						if(user.getName().toLowerCase().equals(userName.toLowerCase())){
							userNameFound = true;
							break;
						}
					}
					
					if(userNameFound){
						throw new UserExistsException();
					}else{
						User u = new User(); 
						Key userKey = new KeyFactory.Builder(Group.class.getSimpleName(), groupName).addChild(User.class.getSimpleName(), email).getKey();
						u.setKey(userKey);
						u.setEmail(email);
						u.setName(userName);
						u.setSaldo(BigDecimal.ZERO);
						u.setPassword(password);
						g.getUsers().add(u);
						pm.close();
						Key k = u.getKey();
						@SuppressWarnings("unused")
						Long l = k.getId();
						return u;					
					}
				}else{
					pm.close();
					throw new GroupPassIncorrectException();
				}
			} catch (GroupDoesNotExistException ge){
				throw ge;
			}
		} catch (WrongPasswordException e) {
			throw new UserExistsException();
		}
		
	}
	
	public static String getGroupInfo(String groupName) throws GroupDoesNotExistException {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		String dataXml = "";		
		try {
			Group g = getGroup(pm, groupName);				
			dataXml += g.toVerbalXmlString();
			pm.close();
			return dataXml;
		} catch (GroupDoesNotExistException e) {
			throw e;
		}

	}	
}
